import type { FeatureItem, ModuleId } from '../module/config_manager/types'
import { withRefreshLoader } from '../components/refresh_loader'
import { ToggleSwitch } from '../components/toggle_switch'
import { BaseModule } from '../lib/abstract'
import { ICON_IDS } from '../lib/icons/types/constants'
import { ToolKit } from '../lib/utils/toolkit'
import { ConfigManager } from '../module/config_manager'
import { AppModule } from '../module/config_manager/types'
import { ModuleManager } from '../module/module_manager'
import { QuickScroll } from '../module/page_enhancer/interaction/quick_scroll'
import {
  BADGE_EFFECT_CLASSNAMES,
  FEATURE_CATEGORIES_NAME,
  generateAllEffectStyles,
  getEffectStyle,
  getTitleThemeClassName,
  logger,
  PROJECT_PREFIX,
} from '../types/constants'
import { EffectType } from '../types/interfaces'

/**
 * 功能开关模块（单例模式）
 */
export class FeatureToggle extends BaseModule {
  readonly id: string = 'feature_toggle'
  readonly name: string = 'featureToggle'
  readonly isInitialized: boolean = false
  readonly supportedPlatforms?: string[] | undefined
  features: FeatureItem[] = []
  registerModules: string[] = []
  private configManager: ConfigManager = ConfigManager.getInstance()
  private moduleManager: ModuleManager = ModuleManager.getInstance()
  private static instance: FeatureToggle
  private activeFeature: Set<string> = new Set()
  private hasActivatedMixedFeature: Set<string> = new Set()

  /**
   * 获取单例实例
   */
  static getInstance(): FeatureToggle {
    if (!FeatureToggle.instance) {
      FeatureToggle.instance = new FeatureToggle()
    }
    return FeatureToggle.instance
  }

  init(): Promise<void> | void {
  }

  destroy(): Promise<void> | void {
    this.removeEventListeners()
    this.cleanupReferences()
  }

  removeEventListeners(): void {
    // 1. 移除功能开关的 change 事件
    document.querySelectorAll('.feature-item input[type="checkbox"]').forEach((checkbox) => {
      checkbox.removeEventListener('change', this.handleCheckboxChange)
    })
  }

  cleanupReferences(): void {
  }

  core(): Promise<void> | void {
  }

  onToggleCallback(_id: string, _checked: boolean): Promise<void> | void {
  }

  /**
   * 刷新功能项
   */
  refreshFeature(): void {
    const platformModules = this.configManager.getPlatformModules()

    const newModules = platformModules
      .filter(module => !this.registerModules.includes(module.id))
      .map(module => module.id)
    const removeModules = this.registerModules
      .filter(module => !platformModules.map(module => module.id).includes(module))

    // 重新注册服务
    this.registerFeatures(platformModules)
    this.unregisterFeatures(this.features.filter(module => removeModules.includes(module.id)))
    // 更新 UI
    this.updateFeatureUI()

    if (newModules.length > 0)
      logger.info(`[${this.name}] 新增模块`, newModules.join(', '))

    if (removeModules.length > 0)
      logger.info(`[${this.name}] 移除模块`, removeModules.join(', '))
  }

  /**
   * 更新功能列表 UI
   */
  updateFeatureUI(): void {
    const container = document.querySelector('.features-container')

    if (container) {
      container.innerHTML = this.generateHTML()
      this.handleOpen() // 重新绑定事件
    }
  }

  /**
   * 注册功能项
   * @param features 要注册的功能项数组
   */
  registerFeatures(features: FeatureItem[]): void {
    // 过滤掉已存在的功能项
    const newFeatures = features.filter(
      newFeature => !this.features.some(existingFeature => existingFeature.id === newFeature.id && existingFeature.show === newFeature.show),
    )

    this.registerModules = [
      ...this.registerModules,
      ...newFeatures.map(feature => feature.id),
    ]

    // 合并功能项
    this.features = [...this.features, ...newFeatures]
    this.storage.set('features', this.features)

    this.setFeatureStates(newFeatures)
  }

  /**
   * 注销功能项
   * @param features 要注销的功能项数组
   */
  unregisterFeatures(features: FeatureItem[]): void {
    this.registerModules = this.registerModules
      .filter(module => !features.map(feature => feature.id).includes(module))

    // 合并功能项
    this.features = this.features
      .filter(feature => !features.map(feature => feature.id).includes(feature.id))
    this.storage.set('features', this.features)

    this.setFeatureStates(features, true)
  }

  /**
   * 设置功能状态
   * @param features 要设置状态的功能项数组
   * @param temporaryClose 是否临时关闭（默认：false）
   */
  private setFeatureStates(features: FeatureItem[], temporaryClose: boolean = false): void {
    const ThemeStyleStatus = this.getFeatureEnabled(AppModule.ThemeStyle.id, temporaryClose)

    features.forEach(async (feature) => {
      let currentValue = this.getFeatureEnabled(feature.id, temporaryClose)

      // 主题样式直接影响是否开启主题继承和主题同步功能
      if ([AppModule.ThemeInherit.id, AppModule.ThemeSync.id].includes(feature.id)) {
        currentValue = ThemeStyleStatus
      }

      const effectType = feature.effectType ?? EffectType.IMMEDIATE

      await this.configManager.setFeatureEnabled(feature.id, currentValue, {
        effectType,
        first: !temporaryClose,
        temporary: temporaryClose,
      })

      this.recordFeatureStatus(feature.id, currentValue, effectType)
    })
  }

  /**
   * 记录功能状态
   * @param featureId 功能项 ID
   * @param value 功能状态值
   * @param effectType 效果类型
   */
  recordFeatureStatus(featureId: string, value: boolean, effectType: EffectType): void {
    if (value) {
      if (effectType === EffectType.MIXED) {
        this.hasActivatedMixedFeature.add(featureId)
      }

      this.activeFeature.add(featureId)
    }
    else {
      this.activeFeature.delete(featureId)
    }
  }

  /**
   * 获取功能状态
   */
  getFeatureEnabled(featureId: string, temporaryClose: boolean = false): boolean {
    return temporaryClose ? false : this.configManager.getFeatureEnabled(featureId)
  }

  generateHTML(first: boolean = true): string {
    // 按分类分组功能
    const categorizedFeatures = this.features
      .filter(item => item.show)
      .reduce((acc, feature) => {
        const category = feature.category || 'unknown' // 默认分类
        if (!acc[category]) {
          acc[category] = []
        }
        acc[category].push(feature)
        return acc
      }, {} as Record<FeatureCategory, FeatureItem[]>)

    // 对每个分类的功能按名称排序
    Object.values(categorizedFeatures).forEach((features) => {
      features.sort((a, b) => a.name.localeCompare(b.name))
    })

    // 生成分类 HTML
    const categoriesHtml = Object.entries(categorizedFeatures)
      .sort(([categoryA], [categoryB]) => categoryA.localeCompare(categoryB))
      .map(([category, features]) => {
        const featuresHtml = features.map((feature) => {
          const {
            id,
            name,
            description,
            effectType = EffectType.IMMEDIATE,
            icon,
            version,
            releaseDate,
            changelog,
            isLoggedIn,
            loginRequired,
          } = feature

          const disabled = loginRequired && isLoggedIn === false
          const currentValue = disabled ? false : this.getToggleSwitchStatus(id)
          let effectConfig = getEffectStyle(effectType, currentValue)

          // 处理刷新生效
          if (effectType === EffectType.MIXED) {
            effectConfig = getEffectStyle(
              effectType,
              currentValue,
              { first: first && !this.hasActivatedMixedFeature.has(id) },
            )
          }

          // 处理登录要求
          if (disabled)
            effectConfig = getEffectStyle(EffectType.IMMEDIATE, undefined, { isLoggedIn })

          const labelText = effectConfig.label
          const toggleSwitch = new ToggleSwitch({
            id,
            checked: currentValue,
            effectType,
            disabled,
          })

          return `
          <div class="feature-item" data-feature-id="${id}" data-effect="${effectType}">
            <div class="feature-base">
              <div class="feature-info">
                <div class="feature-header">
                  <span class="icon">${icon}</span>
                  <span class="text" style="font-weight: bold;">${name}</span>
                </div>
                ${releaseDate && this.isNewFeature(releaseDate) ? `<span class="new-badge">NEW</span>` : ''}
                <span class="effect-badge ${effectConfig.className}">${labelText}</span>
                ${description ? `<p class="feature-desc">${description}</p>` : ''}
              </div>
              ${toggleSwitch.render()}
            </div>
            <div class="feature-attr">
              ${version
                ? `<div class="release-version" title="${changelog}">${version}</div>`
                : ''}
              ${releaseDate
                ? `<div class="release-date">${releaseDate}</div>`
                : ''}
            </div>
          </div>
        `
        }).join('')

        return `
        <div class="feature-category">
          <h3 class="category-title ${getTitleThemeClassName('PRIMARY', ToolKit.browser.theme.getCurrentTheme())}">${FEATURE_CATEGORIES_NAME[category as FeatureCategory]}(${features.length})</h3>
          <div class="category-features">
            ${featuresHtml}
          </div>
        </div>
      `
      })
      .join('')

    return `
    <div class="features-container">
      ${categoriesHtml}
    </div>
  `
  }

  /**
   * 获取快速滚动按钮状态
   */
  getQuickScrollStatus(): boolean | null {
    const quickScroll = QuickScroll.getInstance()
    const $quickScroll = $(`body > .${quickScroll.scrollButton?.idClass}`)

    let show: boolean | null = null

    if ($quickScroll && $quickScroll.length)
      show = $quickScroll.is(':visible')

    return show
  }

  /**
   * 获取功能开关状态
   * @param featureId 功能ID
   * @returns 功能开关状态
   */
  getToggleSwitchStatus(featureId: ModuleId): boolean {
    const status = this.configManager.getFeatureEnabled(featureId)

    if (featureId === AppModule.QuickScroll.id) {
      const show = this.getQuickScrollStatus()
      return show === null ? false : status
    }

    return status
  }

  handleOpen(): void {
    document.querySelectorAll('.feature-item input[type="checkbox"]').forEach((checkbox) => {
      checkbox.addEventListener('change', this.handleCheckboxChange)
    })
  }

  /**
   * 处理复选框变化事件
   * @param e 事件对象
   */
  private handleCheckboxChange = async (e: Event) => {
    const input = e.currentTarget as HTMLInputElement
    const item = (e.currentTarget as HTMLElement).closest('.feature-item')!
    const label = item.querySelector('.toggle-label')!
    const effectType = item.getAttribute('data-effect') as EffectType
    const badge = item.querySelector('.effect-badge') as HTMLElement

    this.updateEffectBadge(badge, effectType, input.checked)

    // 切换标签文本
    label.textContent = input.checked ? '' : ''

    // 触发动画效果
    badge.classList.add('effect-animate')
    setTimeout(() => badge.classList.remove('effect-animate'), 500)

    // 触发统计信息更新事件
    this.eventEmitter.emit('stats-updated')

    const featureId = item.getAttribute('data-feature-id')

    if (!featureId)
      return

    await this.configManager.setFeatureEnabled(featureId, input.checked, {
      effectType,
    })

    this.recordFeatureStatus(featureId, input.checked, effectType)
  }

  /**
   * 更新徽章
   * @param badge 徽章元素
   * @param effectType 生效类型
   * @param checked 是否选中
   */
  private updateEffectBadge(badge: HTMLElement, effectType: EffectType, checked: boolean) {
    if (![EffectType.IMMEDIATE, EffectType.MIXED].includes(effectType))
      return

    const $badge = $(badge)
    const featureId = $badge.closest('[data-feature-id]').attr('data-feature-id')!
    let first

    if (effectType === EffectType.MIXED) {
      first = !this.hasActivatedMixedFeature.has(featureId)
    }
    else if (effectType === EffectType.IMMEDIATE) {
      first = !this.activeFeature.has(featureId)
    }

    const effectConfig = getEffectStyle(effectType, checked, { first })

    $badge.text(effectConfig.label)
      .removeClass(BADGE_EFFECT_CLASSNAMES.join(' '))
      .addClass(effectConfig.className)
  }

  /**
   * 批量操作开关状态
   * @param enable 是否启用
   * @param selector 目标选择器（可选自定义）
   */
  private toggleAllFeatures(enable: boolean, selector = '.feature-item input[type="checkbox"]') {
    const checkboxes = document.querySelectorAll<HTMLInputElement>(selector)
    const totalCount = checkboxes.length
    let changedCount = 0

    checkboxes.forEach((checkbox) => {
      if (checkbox.checked !== enable) {
        checkbox.checked = enable
        // 触发 change 事件保证响应式框架能捕获变化
        checkbox.dispatchEvent(new Event('change', { bubbles: true }))
        changedCount++
      }
    })

    if (changedCount > 0) {
      const desc = enable ? '开启' : '关闭'
      if (totalCount === changedCount) {
        logger.important(`[${this.name}] 所有功能已全部${desc}，全部功能（${totalCount}）状态发生改变`)
      }
      else {
        logger.important(`[${this.name}] 所有功能已全部${desc}，部分功能（${changedCount}/${totalCount}）状态发生改变`)
      }
    }
    else {
      logger.warn(`[${this.name}] 所有功能已是${enable ? '开启' : '关闭'}状态，无需操作`)
    }

    return changedCount
  }

  /**
   * 启用所有功能
   */
  enableAll(): number {
    return this.toggleAllFeatures(true)
  }

  /**
   * 禁用所有功能
   */
  disableAll(): number {
    return this.toggleAllFeatures(false)
  }

  /**
   * 获取已启用的功能数量
   */
  getEnabledCount(selector = '.feature-item input[type="checkbox"]'): number {
    const checkboxes = Array.from(document.querySelectorAll<HTMLInputElement>(selector))
    return checkboxes.filter(checkbox => checkbox.checked).length
  }

  /**
   * 获取总功能数量
   */
  getTotalCount(selector = '.feature-item input[type="checkbox"]'): number {
    return document.querySelectorAll<HTMLInputElement>(selector).length
  }

  /**
   * 更新功能开关统计信息
   * @returns 更新后的启用数量和总数
   */
  updateFeatureStats(): { enabled: number, total: number } {
    const enabled = this.getEnabledCount()
    const total = this.getTotalCount()

    return { enabled, total }
  }

  private isNewFeature(dateString: string): boolean {
    try {
      // 验证日期格式
      if (!/^\d{4}-\d{2}-\d{2}$/.test(dateString)) {
        logger.warn(`Invalid date format: ${dateString}, expected YYYY-MM-DD`)
        return false
      }

      const releaseDate = new Date(dateString)

      // 检查日期有效性
      if (Number.isNaN(releaseDate.getTime())) {
        logger.warn(`Invalid date: ${dateString}`)
        return false
      }

      const currentDate = new Date()
      const dayDiff = (currentDate.getTime() - releaseDate.getTime()) / (86400000)

      // 未来日期不算新功能
      if (dayDiff < 0)
        return false

      return dayDiff <= 15
    }
    catch (error: any) {
      logger.error(`Date check failed: ${error}`)
      return false
    }
  }

  /**
   * 重置所有功能开关状态存储信息并刷新页面
   */
  reset(): void {
    // 1. 删除功能开关状态信息
    this.storage.deleteBatch({ useDomainIsolation: true, useNamespace: false, includeGlobal: false, prefix: this.configManager.featureStoragePrefix })

    // 2. 删除模块配置信息
    this.moduleManager.activeModules.forEach((moduleName) => {
      const module = this.moduleManager.getModule(moduleName)
      if (module && module.id) {
        this.storage.delete(`config#${module.id}`, false, { useDomainIsolation: true })
      }
    })

    // 3. 刷新页面
    withRefreshLoader()
  }

  /**
   * 获取样式定义
   */
  styles(): string {
    return `
      .features-container {
        all: initial !important;
        display: flex;
        flex-direction: column;
        gap: 15px;
        max-height: 60vh;
        overflow-y: auto;
        
        .feature-category {
          background: var(--${PROJECT_PREFIX}-theme-bg-base) !important;
          border-radius: 8px;
          padding: 0;
          margin-bottom: 20px;
          box-shadow: 0 2px 4px rgba(0,0,0,0.05);
          border: 1px solid var(--${PROJECT_PREFIX}-theme-border-primary) !important;
          .category-features {
            display: grid;
            padding: 15px;
            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
            gap: 15px;
          }
        }

        .feature-item {
          position: relative;
          background: var(--${PROJECT_PREFIX}-theme-discussion-bg-odd);
          box-shadow: var(--${PROJECT_PREFIX}-theme-discussion-shadow-odd);
          border-radius: 8px;
          margin-top: 20px;
          display: flex;
          flex-direction: column;
          
          .feature-base {
            position: relative;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 40px 10px;
            transition: all 0.3s ease;
            
            .feature-info {
              flex: 1;
              padding-right: 60px; /* 为标签留出空间 */
              
              .feature-header {
                margin: 0 0 6px 0;
                margin-right: 50px; /* 防止与标签重叠 */
                font-size: 15px;
                white-space: nowrap; /* 不换行 */
                color: var(--${PROJECT_PREFIX}-theme-text-secondary);
                display: inline-flex;
                align-items: center;
                
                .icon {
                  font-size: 15px !important;
                  margin-top: -2px;
                  margin-right: 5px;
                }
              }
              
              ${generateAllEffectStyles()}
              
              .new-badge {
                position: absolute;
                top: 8px;
                left: 8px;
                font-size: 8px;
                padding: 2px 6px;
                border-radius: 10px;
                font-weight: bold;
                user-select: none !important;
                background: linear-gradient(135deg, #ff6b81, #ff8e53);
                color: white;
              }

              .feature-desc {
                margin: 0;
                font-size: 13px;
                color: #6c757d;
                line-height: 1.4;
              }
            }
          }
          .feature-attr {
            position: absolute;
            bottom: 0.5em;
            display: flex;
            flex-direction: row;
            align-items: center;
            justify-content: space-between;
            width: 100%;
            
            .release-version, .release-date {
              display: inline-flex;
              align-items: center;
              font-size: 12px;
              font-weight: normal;
              color: var(--${PROJECT_PREFIX}-theme-text-secondary) !important;
              padding: 8px;
              &::before {
                ${this.stylesService.inlinePseudo.icon()}
              }
            }
            .release-version::before {
              background-image: var(${this.themeVarService.generateIcon(ICON_IDS.development.version)}) !important;
            }
            .release-date::before {
              background-image: var(${this.themeVarService.generateIcon(ICON_IDS.development.update)}) !important;
            }
          }
        }
      }
    `
  }

  applyConfig(_config: any): void {
  }
}
